﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MessageAPI;
using System.Diagnostics;
using Microsoft.WindowsAPICodePack.Taskbar;
using System.Reflection;
using System.IO;
using System.Security.Principal;

namespace WinShare
{
    public partial class Form1 : Form
    {
        // Application IDs that are used for the Windows 7 Taskbar Jumplists
        private const string appId = "WinShare";
        private const string progId = "WinShare";

        // commService is used for all network communication 
        public Broadcast_Service commService = null;
        // Used for updating text on the form. Required because of threading issues in netowork API
        public delegate void HandleMessageCallback(MessageAPI.UdpMessage text);

        // Used for sending and recieving Windows Messages
        WindowsMessageAPI.MessageHandler msgService;
        // Message ID for 'ShareSite' message
        IntPtr ShareSite;

        // Taskbar Jumplist variables
        private TaskbarManager windowsTaskbar;
        private JumpList jumpList;
        // Paths to current execution environment (used for jumplists)
        private string executableFolder;
        private readonly string executablePath;

        // Variable for Keep-Alive Lock
        private bool stayAlive = false;

        // Variable for group chat form
        GroupChat groupChat;

        // Containts all recieved messages
        List<MessageAPI.UdpMessage> recievedMessages = new List<UdpMessage>();

        // Specifies if ShareSiteForm needs to be shown on start
        bool newShareSite = false;

        public Form1(bool shareSite = false)
        {
                InitializeComponent();
                // Setup network message system
                commService = new MessageAPI.Broadcast_Service(5683);
                // Only recieve messages directed to this user
                commService.onlyMyMessages = true;
                // Handle network events
                commService.OnServiceStarted += new Broadcast_Service.ServiceStarted(this.commService_ServiceStarted);
                commService.OnMessageRecieved += new Broadcast_Service.MessageRecieved(this.commService_MessageRecieved);
                commService.OnMessageSuccess += new Broadcast_Service.MessageSuccess(commService_OnMessageSuccess);
                // Start network message service
                commService.startService();

                // Save current folder and path of running executable
                executablePath = Assembly.GetEntryAssembly().Location;
                executableFolder = Path.GetDirectoryName(executablePath);

                if (Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1)
                {
                    windowsTaskbar = TaskbarManager.Instance;
                    // Set ApplicationId so we can use Jumplists
                    windowsTaskbar.ApplicationId = appId;
                    this.notifyIcon1.Icon = WinShare.Properties.Resources.WinShare2;
                    this.Icon = WinShare.Properties.Resources.WinShare2;
                }
                else
                {
                    this.notifyIcon1.Icon = WinShare.Properties.Resources.WinShareTray;
                    this.Icon = WinShare.Properties.Resources.WinShareTray;
                }

                // Setup listening for Windows Messages
                msgService = new WindowsMessageAPI.MessageHandler("WinShare-Server");
                // Register "ShareSite" message
                ShareSite = msgService.RegisterMessage("ShareSite");
                // Create filter so we don't recieve every single message that comes in
                msgService.MessageFilters.Add(ShareSite);
                // Handle message events
                msgService.OnMessageReceived += new WindowsMessageAPI.MessageHandler.MessageRecieved(msgService_OnMessageReceived);

                newShareSite = shareSite;
        }

        void msgService_OnMessageReceived(object sender, Message msg)
        {
            if (msg.Msg == ShareSite.ToInt32())
            {
                ShowShareSiteForm();
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            if (Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 1)
            {
                jumpList = JumpList.CreateJumpList();
                JumpListLink shareLink = new JumpListLink(executablePath, "Share a website");
                shareLink.Arguments = "/shareasite";
                jumpList.AddUserTasks(shareLink);
                jumpList.Refresh();
            }

            if(newShareSite == true)
            {
                ShowShareSiteForm();
            }
        }

        private void commService_MessageRecieved(object sender, MessageAPI.UdpMessage message)
        {
            // Use invoke stuff because of API threading issues.
            /*this.Invoke(new UpdateTextCallback(this.AppendMessage),
                    new object[] { message.SenderUser.UserName + ": " + message.Message }); */
            this.Invoke(new HandleMessageCallback(this.HandleMessage),
                    new object[] { message });
        }

        private void commService_ServiceStarted(object sender)
        {
            Debug.WriteLine("Service Started!");
        }

        private void commService_OnMessageSuccess(object sender)
        {
            // Debug.WriteLine("Message Sent Successfully!");
        }
        
        private void HandleMessage(MessageAPI.UdpMessage text)
        {
            // Add message to recieved messages list
            recievedMessages.Add(text);
            // Set the textbox text.
            lbxRecieved.Items.Add(text.SenderUser.UserName + ": " + text.Message);
            if (text.SenderUser.UserName != WindowsIdentity.GetCurrent().Name)
            {
                // Notify user of new website shared with them
                notifyIcon1.Visible = true;   
                notifyIcon1.ShowBalloonTip(7000, "New Website Shared", text.SenderUser.UserName + " shared " + text.Message, ToolTipIcon.Info);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason != CloseReason.WindowsShutDown && stayAlive == true)
            {
                e.Cancel = true;
            } else {
                if (groupChat != null)
                {
                    groupChat.destroy();
                }
                commService.destroy();
                msgService.Dispose();
            }
            
        }

        private void ShowShareSiteForm()
        {
            ShareSiteForm newSite = new ShareSiteForm();
            if (newSite.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                sendMessage(newSite.WebSite);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ShowShareSiteForm();
        }

        public void sendMessage(UdpMessage message)
        {
            commService.sendMessage(message);
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control == true && e.Shift == true)
            {
                switch (e.KeyCode)
                {
                    case Keys.R:
                        if (stayAlive == true)
                        {
                            stayAlive = false;
                        }
                        else
                        {
                            stayAlive = true;
                        }
                        break;
                    case Keys.G:
                        groupChat = new GroupChat();
                        groupChat.Show();
                        break;
                    case Keys.E:
                        MessageBox.Show("Haha, you didn't think I would give you the real codes did you?");
                        break;
                    case Keys.S:
                        aboutConfig configEditor = new aboutConfig();
                        configEditor.ShowDialog();
                        break;
                }
            }
        }

        private void lbxRecieved_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (lbxRecieved.SelectedItem != null)
            {
                try
                {
                    // Open Browser with currently selected website
                    Process webBrowser = new Process();
                    webBrowser.StartInfo.UseShellExecute = true;
                    webBrowser.StartInfo.FileName = recievedMessages[lbxRecieved.SelectedIndex].Message;
                    webBrowser.Start();
                }
                catch (Win32Exception w32ex)
                {
                    MessageBox.Show("Error opening this website: " + w32ex.Message);
                }

            }
        }

        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
            this.Activate();
        }

        private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
        {
            if (MessageBox.Show("An update for Winshare is available. Update now? (Recommended)", "Update Avalable", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.Yes)
            {
                Program.checkUpdates(WinShare.Properties.Settings.Default.Update_Location);
                Application.Exit();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            if (WinShare.Properties.Settings.Default.Updates_Enabled == true)
            {
                fileSystemWatcher1.Path = WinShare.Properties.Settings.Default.Update_Location;
                fileSystemWatcher1.EnableRaisingEvents = true;
            }
        }
    }
}
